package cn.com.self.apis.file.exception;

import cn.com.self.apis.file.response.BaseResponse;
import cn.com.self.apis.file.response.BaseResponseStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.Iterator;
import java.util.List;


/**
 * 异常拦截类
 *
 * @author Leng.c
 * @Date 2020-10-21 19:20
 */
@ControllerAdvice
@Slf4j
public class GlobalException {


    /**
     * 全局异常捕捉处理
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public BaseResponse errorHandler(Exception e) {
        log.error("系统异常", e);
        return new BaseResponse<>(BaseResponseStatus.FAILURE, "系统繁忙,请稍后再试!");
    }


    /**
     * 业务异常捕捉处理
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = BussinessException.class)
    public BaseResponse errorHandler(BussinessException e) {
        log.error("业务异常", e);
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getDefaultMessage());
    }

    /**
     * 运行时异常捕捉处理
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = RuntimeException.class)
    public BaseResponse errorHandler(RuntimeException e) {
        log.error("运行时异常", e.getMessage());
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getMessage());
    }

    /**
     * 入参字段校验异常 RequestParameter
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public BaseResponse errorHandler(MissingServletRequestParameterException e) {
        log.error("入参字段校验异常", e.getMessage());
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getMessage());
    }

    /**
     * 401 - No premission
     */
    @ExceptionHandler({SecurityException.class})
    public BaseResponse handleSecurityException(SecurityException e) {
        log.error("未授权，禁止访问", e);
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getMessage());
    }

    /**
     * 400 - Bad Request
     */
    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    public BaseResponse handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        log.error("参数解析失败", e);
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getMessage());
    }

    /**
     * 405 - Method Not Allowed
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public BaseResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("不支持当前请求方法", e);
        return new BaseResponse(BaseResponseStatus.FAILURE, e.getMessage());
    }

    /**
     * 入参字段校验异常 Valid
     *
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public BaseResponse errorHandler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
        String message = this.buildValidationMessage(bindingResult);
        log.error(" 入参字段,校验异常", message);
        return new BaseResponse(BaseResponseStatus.FAILURE, message);
    }

    private String buildValidationMessage(BindingResult bindingResult) {
        StringBuilder sb = new StringBuilder();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        Iterator var4 = fieldErrors.iterator();

        while (var4.hasNext()) {
            FieldError error = (FieldError) var4.next();
            sb.append(error.getField()).append(":");
            sb.append(error.getDefaultMessage()).append("\n ");
        }
        return sb.toString();
    }
}
